﻿using DocBot.Objects;
using DocBot.Util;
using DocBot.Util.Collections;
using DocBot.Util.Service;
using DocBot.ViewModel;

using GalaSoft.MvvmLight.Command;

using IrcDotNet;

using System;
using System.Linq;
using System.Text.RegularExpressions;
using System.Threading;
using System.Timers;
using System.Windows.Input;

namespace DocBot.Bot
{
	public class InsireBot : IDisposable
	{
		#region Properties
		private static MainWindow _window;
		private static IrcClient _ircclient;
		private static PlaylistViewModel _playlist;
		private static AudioDeviceViewModel _audiodevices;
		private static LogViewModel _log;
		private static ChatViewModel _chat;
		private static CustomCommandViewModel _customcommands;
		private static BlacklistViewModel _blacklist;
		private static IrcUserRegistrationInfo _ircuserinfo;
		private static APIManager _manager;


		System.Timers.Timer _MessageTimer = new System.Timers.Timer();

		private const int clientQuitTimeout = 1000;

		private bool isDisposed = false;
		#endregion

		#region Construction and Cleanup
		public InsireBot(MainWindow mainwindow)
		{
			_window = mainwindow;
			_manager = new APIManager(_window);
			_playlist = (PlaylistViewModel)_window.Playlist.DataContext;
			_log = (LogViewModel)_window.FindResource("LogModel");
			_chat = (ChatViewModel)_window.Chat.DataContext;
			_customcommands = (CustomCommandViewModel)_window.CustomCommands.DataContext;
			_blacklist = (BlacklistViewModel)_window.Blacklist.DataContext;

			if (!Settings.Instance.IsDefaultConfig)
				this.initializeIRC();

			_MessageTimer.Elapsed += MessageTimer_Elapsed;
			_MessageTimer.Interval = 1250;
			_MessageTimer.Start();
		}

		void MessageTimer_Elapsed(object sender, ElapsedEventArgs e)
		{
			if (_manager.AnswerQueue != null)
				if (_manager.AnswerQueue.Count > 0)
					switch (_manager.AnswerQueue.Count)
					{
						case 1:
							while (_manager.AnswerQueue.Count > 0)
							{
								_ircclient.LocalUser.SendMessage(Settings.Instance.IRC_TargetChannel, _manager.AnswerQueue.Dequeue() + " has been added to the Playlist");
							}
							break;
						default:
							int i = 0;
							while (_manager.AnswerQueue.Count > 0)
							{
								i++;
								_manager.AnswerQueue.Dequeue();
							}

							_ircclient.LocalUser.SendMessage(Settings.Instance.IRC_TargetChannel, i + " Songs have been added to the Playlist.");
							break;

					}

			if (_manager.AlreadyParsedQueue != null)
				if (_manager.AlreadyParsedQueue.Count > 0)
					switch (_manager.AlreadyParsedQueue.Count)
					{
						case 1:
							while (_manager.AlreadyParsedQueue.Count > 0)
							{
								_ircclient.LocalUser.SendMessage(Settings.Instance.IRC_TargetChannel, _manager.AlreadyParsedQueue.Dequeue() + " is already on the Playlist");
							}
							break;
						default:
							int i = 0;
							while (_manager.AlreadyParsedQueue.Count > 0)
							{
								i++;
								_manager.AlreadyParsedQueue.Dequeue();
							}

							_ircclient.LocalUser.SendMessage(Settings.Instance.IRC_TargetChannel, i + " Songs were already on the Playlist.");
							break;
					}

			if (_manager.BlacklistedQueue != null)
				if (_manager.BlacklistedQueue.Count > 0)
					switch (_manager.BlacklistedQueue.Count)
					{
						case 1:
							while (_manager.BlacklistedQueue.Count > 0)
							{
								_ircclient.LocalUser.SendMessage(Settings.Instance.IRC_TargetChannel, _manager.BlacklistedQueue.Dequeue() + " was caught in the Blacklistfilter");
							}
							break;
						default:
							int i = 0;
							while (_manager.BlacklistedQueue.Count > 0)
							{
								i++;
								_manager.BlacklistedQueue.Dequeue();
							}

							_ircclient.LocalUser.SendMessage(Settings.Instance.IRC_TargetChannel, i + " Songs were caught in the Blacklistfilter");
							break;
					}

			if (Messenger.Instance.Messages != null)
				if (Messenger.Instance.Messages.Count > 0)
				{
					Message m = Messenger.Instance.Messages.Dequeue();
					switch (m.Type)
					{
						case MessageType.Chat:
							if (Settings.Instance.ReplyToChat && _ircclient.Channels.Count > 0)
								_ircclient.LocalUser.SendMessage(Settings.Instance.IRC_TargetChannel, m.Information);
							break;
						case MessageType.Log: _log.Add(m.Information);
							break;
						case MessageType.LogAndChat:
							if (Settings.Instance.ReplyToChat && _ircclient.Channels.Count > 0)
								_ircclient.LocalUser.SendMessage(Settings.Instance.IRC_TargetChannel, m.Information);
							_log.Add(m.Information);
							break;
					}
				}
		}

		~InsireBot()
		{
			Dispose(false);
		}

		protected void Dispose(bool disposing)
		{
			if (!this.isDisposed)
			{
				if (disposing)
				{
					if (_ircclient != null)
					{
						_ircclient.Quit(clientQuitTimeout, Settings.Instance.IRC_QuitMessage);
						_ircclient.Dispose();
					}
				}
			}
			this.isDisposed = true;
		}

		public void Dispose()
		{
			Dispose(true);
			GC.SuppressFinalize(this);
		}

		public void initializeIRC()
		{
			_ircuserinfo = new IrcUserRegistrationInfo()
		   {
			   NickName = Settings.Instance.IRC_Username,
			   UserName = Settings.Instance.IRC_Username,
			   RealName = Settings.Instance.IRC_Username,
			   Password = Settings.Instance.IRC_Password
		   };

			if (Settings.Instance.IRC_AutoConnect)
				this.Connect.Execute(true);
			Messenger.Instance.Messages.Enqueue(new Message("IRC initialized", MessageType.Log));
		}
		#endregion

		#region IRC Client Event Handlers
		/// <summary>
		/// fires when the irc client successfully connected
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		private void IrcClient_Connected(object sender, EventArgs e)
		{
			if (Settings.Instance.DebugMode)
			{
				Messenger.Instance.Messages.Enqueue(new Message("Now connected to " + Settings.Instance.IRC_Serveradress, MessageType.Log));
				Messenger.Instance.Messages.Enqueue(new Message("Attempting to join: " + Settings.Instance.IRC_TargetChannel, MessageType.Log));
			}
			_ircclient.Channels.Join(Settings.Instance.IRC_TargetChannel);

			while (_ircclient.Channels.Count == 0)
			{
				//nothing so wait on the channel count to raise above zero
			}

			if (_ircclient.Channels.Count > 0)
			{
				if (_ircclient.Channels.Where(p => p.Name == Settings.Instance.IRC_TargetChannel).Count() == 1)
				{
					if (Settings.Instance.DebugMode)
						Messenger.Instance.Messages.Enqueue(new Message("Joined channel: " + Settings.Instance.IRC_TargetChannel, MessageType.Log));
					_ircclient.Channels[0].MessageReceived += OnChannelMessageReceived;
				}
			}
		}

		private void IrcClient_Registered(object sender, EventArgs e)
		{
			var client = (IrcClient)sender;

			client.LocalUser.NoticeReceived += IrcClient_LocalUser_NoticeReceived;
			client.LocalUser.MessageReceived += IrcClient_LocalUser_MessageReceived;
			client.LocalUser.JoinedChannel += IrcClient_LocalUser_JoinedChannel;
			client.LocalUser.LeftChannel += IrcClient_LocalUser_LeftChannel;

		}

		private void IrcClient_LocalUser_NoticeReceived(object sender, IrcMessageEventArgs e)
		{
			var localUser = (IrcLocalUser)sender;

			Messenger.Instance.Messages.Enqueue(new Message("in " + ((IrcLocalUser)sender).UserName + " received " + e.Text, MessageType.Log));
		}

		private void IrcClient_Channel_MessageReceived(object sender, IrcMessageEventArgs e)
		{
			var channel = (IrcChannel)sender;

			if (e.Source is IrcUser)
			{

			}
			OnChannelMessageReceived(channel, e);

		}

		private void IrcClient_LocalUser_MessageReceived(object sender, IrcMessageEventArgs e)
		{
			var localUser = (IrcLocalUser)sender;

			if (e.Source is IrcUser)
			{
				if (Settings.Instance.DebugMode)
					Messenger.Instance.Messages.Enqueue(new Message(((IrcLocalUser)sender).UserName + " received " + e.Text, MessageType.Log));
			}
		}

		private void IrcClient_LocalUser_JoinedChannel(object sender, IrcChannelEventArgs e)
		{
			var localUser = (IrcLocalUser)sender;

			e.Channel.UserJoined += IrcClient_Channel_UserJoined;
			e.Channel.UserLeft += IrcClient_Channel_UserLeft;
			e.Channel.MessageReceived += IrcClient_Channel_MessageReceived;
			e.Channel.NoticeReceived += IrcClient_Channel_NoticeReceived;

			if (Settings.Instance.DebugMode)
				Messenger.Instance.Messages.Enqueue(new Message(((IrcLocalUser)sender).UserName + " joined " + e.Channel, MessageType.Log));
		}

		private void IrcClient_LocalUser_LeftChannel(object sender, IrcChannelEventArgs e)
		{
			var localUser = (IrcLocalUser)sender;

			e.Channel.UserJoined -= IrcClient_Channel_UserJoined;
			e.Channel.UserLeft -= IrcClient_Channel_UserLeft;
			e.Channel.MessageReceived -= IrcClient_Channel_MessageReceived;
			e.Channel.NoticeReceived -= IrcClient_Channel_NoticeReceived;

			if (Settings.Instance.DebugMode)
				Messenger.Instance.Messages.Enqueue(new Message(((IrcLocalUser)sender).UserName + " left " + e.Channel, MessageType.Log));
		}

		private void IrcClient_Channel_UserLeft(object sender, IrcChannelUserEventArgs e)
		{
			if (Settings.Instance.DebugMode)
				Messenger.Instance.Messages.Enqueue(new Message(e.ChannelUser + " left " + ((IrcChannel)sender).Name, MessageType.Log));
		}

		private void IrcClient_Channel_UserJoined(object sender, IrcChannelUserEventArgs e)
		{
			if (Settings.Instance.DebugMode)
				Messenger.Instance.Messages.Enqueue(new Message(e.ChannelUser + " joined in " + ((IrcChannel)sender).Name, MessageType.Log));
		}

		private void IrcClient_Channel_NoticeReceived(object sender, IrcMessageEventArgs e)
		{
			if (Settings.Instance.DebugMode)
				Messenger.Instance.Messages.Enqueue(new Message(((IrcChannel)sender).Name + " send " + e.Text, MessageType.Log));
		}

		/// <summary>
		/// Debug: fires when pong recieved
		/// </summary>
		void _ircclient_PongReceived(object sender, IrcPingOrPongReceivedEventArgs e)
		{
			if (Settings.Instance.DebugMode)
				if (Settings.Instance.DebugMode)
					Messenger.Instance.Messages.Enqueue(new Message("Pong recieved", MessageType.Log));
		}

		/// <summary>
		/// Debug: fires when ping recieved
		/// </summary>
		void _ircclient_PingReceived(object sender, IrcPingOrPongReceivedEventArgs e)
		{
			if (Settings.Instance.DebugMode)
				Messenger.Instance.Messages.Enqueue(new Message("Ping recieved", MessageType.Log));
		}

		/// <summary>
		/// fires when a channel message is recieved
		/// </summary>
		private void OnChannelMessageReceived(object sender, IrcMessageEventArgs e)
		{
			checkForCommand(e.Source, e.Text);
		}

		/// <summary>
		/// fires when the connection failed
		/// </summary>
		private void IrcClient_ConnectFailed(object sender, IrcErrorEventArgs e)
		{
			if (Settings.Instance.DebugMode)
				Messenger.Instance.Messages.Enqueue(new Message("Connection failed: " + e.Error.ToString(), MessageType.Log));
		}

		/// <summary>
		/// fires when the irc client disconnects from the server
		/// </summary>
		public void IrcClient_Disconnected(object sender, EventArgs e)
		{
			if (Settings.Instance.DebugMode)
				Messenger.Instance.Messages.Enqueue(new Message("Disconnected", MessageType.Log));
		}

		/// <summary>
		/// fires when an error from the client is recieved (pretty much handles every error thrown)
		/// </summary>
		void _ircclient_Error(object sender, IrcErrorEventArgs e)
		{
			if (Settings.Instance.DebugMode)
				Messenger.Instance.Messages.Enqueue(new Message("Error: " + e.Error.Message, MessageType.Log));
		}
		#endregion

		/// <summary>
		/// checks the incoming message for a specific command, also checks if the user is blacklisted or not
		/// </summary>
		/// <param name="source">the user</param>
		/// <param name="inputString">the full message</param>
		private void checkForCommand(IIrcMessageSource source, String inputString)
		{
			_chat.add(source.Name, inputString);
			inputString = inputString.ToLower();

			//if first character isnt a '!', the line isnt a valid command
			if (inputString[0] != '!') return;

			//check if user is blacklisted
			if (_blacklist.Items.Where(p => p.Object == source.Name).Count() > 0)
			{
				Messenger.Instance.Messages.Enqueue(new Message(source.Name + " is blacklisted from using bot commands.", MessageType.LogAndChat));
				return;
			}
			//split the string into it's parts
			String[] _parts = inputString.Split(new char[] { ' ' }, 2);

			#region basic commands

			if (Regex.IsMatch(inputString, @"!request"))
			{
				inputString = inputString.Replace("!request", String.Empty).Trim();
				_manager.ParserQueue.Enqueue(inputString);
				return;
			}

			//forceplay command
			if (Regex.IsMatch(inputString, @"!forceplay") || Regex.IsMatch(inputString, @"force"))
			{
				if (checkForOperator(source))
					if (Settings.Instance.IRC_TargetChannel == source.Name || Settings.Instance.IRC_Username == source.Name)
						_window.ForceSongPlay(_parts[1]);
				return;
			}

			//skip command
			if (Regex.IsMatch(inputString, @"!skip") && checkForOperator(source))
			{
				_window.RequestSongSkip(false);
				return;
			}

			//voteskip command
			if (Regex.IsMatch(inputString, @"!voteskip"))
			{
				_window.RequestSongSkip(true);
				return;
			}

			//removesong command
			if (Regex.IsMatch(inputString, @"!removesong") && checkForOperator(source))
			{
				foreach (PlaylistItem p in (_playlist.Songs.Where(p => p.ArtistName.Contains(_parts[1]) || p.SongTitle.Contains(_parts[1]) || p.Url == _parts[1])))
					_playlist.Songs.Remove(p);

				Messenger.Instance.Messages.Enqueue(new Message("Tracks with the keyword \"" + _parts[1] + "\" have been removed from playlist.", MessageType.LogAndChat));
			}

			//banuser command
			if (Regex.IsMatch(inputString, @"!banuser") && checkForOperator(source))
			{
				if (!checkForOperator(_parts[1]))
					if (_blacklist.add(_parts[1].ToLower(), BlackListItemType.User))
						Messenger.Instance.Messages.Enqueue(new Message(_parts[1] + " is now blacklisted from requesting", MessageType.LogAndChat));
					else
						Messenger.Instance.Messages.Enqueue(new Message(_parts[1] + " is already blacklisted from requesting", MessageType.LogAndChat));
				else
					Messenger.Instance.Messages.Enqueue(new Message("Mods can't add Mods to the UserBlacklist", MessageType.LogAndChat));
				return;
			}

			//bansong command
			if (Regex.IsMatch(inputString, @"!bansong") && checkForOperator(source))
			{

				if (_blacklist.add(_parts[1], BlackListItemType.PlaylistItem))
					Messenger.Instance.Messages.Enqueue(new Message(_parts[1] + " blacklisted.", MessageType.LogAndChat));
				else
					Messenger.Instance.Messages.Enqueue(new Message(_parts[1] + " is already blacklisted", MessageType.LogAndChat));
				return;
			}

			//bankeyword command
			if (Regex.IsMatch(inputString, @"!bankeyword") && checkForOperator(source))
			{
				if (_blacklist.add(_parts[1], BlackListItemType.Keyword))
					Messenger.Instance.Messages.Enqueue(new Message("Keyword \"" + _parts[1] + "\" blacklisted.", MessageType.LogAndChat));
				else
					Messenger.Instance.Messages.Enqueue(new Message("Keyword \"" + _parts[1] + "\" is already blacklisted", MessageType.LogAndChat));
				return;
			}

			//unbanuser command
			if (Regex.IsMatch(inputString, @"!unbanuser") && checkForOperator(source))
			{
				if (!checkForOperator(_parts[1]))
					if (_blacklist.remove(_parts[1].ToLower()))
						Messenger.Instance.Messages.Enqueue(new Message(_parts[1] + " removed from blacklist", MessageType.LogAndChat));
					else
						Messenger.Instance.Messages.Enqueue(new Message(_parts[1] + " wasn't blacklisted", MessageType.LogAndChat));
				else
					Messenger.Instance.Messages.Enqueue(new Message("Mods can't remove Mods from the UserBlacklist", MessageType.LogAndChat));
				return;
			}

			//unbansong command
			if (Regex.IsMatch(inputString, @"!unbansong") && checkForOperator(source))
			{
				if (_blacklist.remove(_parts[1]))
					Messenger.Instance.Messages.Enqueue(new Message(_parts[1] + " removed from blacklist.", MessageType.LogAndChat));
				else
					Messenger.Instance.Messages.Enqueue(new Message(_parts[1] + " wasn't blacklisted", MessageType.LogAndChat));
				return;
			}

			//unbankeyword command
			if (Regex.IsMatch(inputString, @"!unbankeyword") && checkForOperator(source))
			{
				if (_blacklist.remove(_parts[1]))
					Messenger.Instance.Messages.Enqueue(new Message("Keyword \"" + _parts[1] + "\" removed from blacklist", MessageType.LogAndChat));
				else
					Messenger.Instance.Messages.Enqueue(new Message("Keyword \"" + _parts[1] + "\" wasn't blacklisted", MessageType.LogAndChat));
				return;
			}

			//checkuser command
			if (Regex.IsMatch(inputString, @"!checkuser"))
			{
				if (_blacklist.Items.Select(p => p.Object == _parts[1].ToLower()).Count() > 0)
				{
					Messenger.Instance.Messages.Enqueue(new Message(_parts[1] + " is blacklisted from requesting.", MessageType.LogAndChat));
					return;
				}
				Messenger.Instance.Messages.Enqueue(new Message(_parts[1] + " is not blacklisted from requesting.", MessageType.LogAndChat));
				return;
			}

			//checksong command
			if (Regex.IsMatch(inputString, @"!checksong"))
			{
				if (_blacklist.Items.Select(p => p.Object == _parts[1].ToLower()).Count() > 0)
				{
					Messenger.Instance.Messages.Enqueue(new Message(_parts[1] + " is blacklisted.", MessageType.LogAndChat));
					return;
				}
				Messenger.Instance.Messages.Enqueue(new Message(_parts[1] + " is not blacklisted.", MessageType.LogAndChat));
				return;
			}

			//checkkeyword command
			if (Regex.IsMatch(inputString, @"!checkkeyword"))
			{
				if (_blacklist.Items.Select(p => p.Object == _parts[1].ToLower()).Count() > 0)
				{
					Messenger.Instance.Messages.Enqueue(new Message("\"" + _parts[1] + "\" is blacklisted.", MessageType.LogAndChat));
					return;
				}
				Messenger.Instance.Messages.Enqueue(new Message("\"" + _parts[1] + "\" is not blacklisted.", MessageType.LogAndChat));
				return;
			}

			#endregion

			#region information commands

			//playlist command
			if (Regex.IsMatch(inputString, @"!playlist"))
			{
				int dur = 0;
				int count = 0;
				string paste = String.Empty;
				//duration
				foreach (PlaylistItem p in _playlist.Songs)
				{
					dur += p.Duration;
					count++;
					paste = paste + p.SongTitle + " " + p.ArtistName + " " + p.Url + " " + p.Duration + Environment.NewLine;
				}
				Messenger.Instance.Messages.Enqueue(new Message("The playlist contains " + count + " tracks with a total duration of " + dur / 60 + " minutes and " + dur % 60 + " seconds.", MessageType.LogAndChat));

				//pastebin url, optional
				if (!Settings.Instance.Pastebin_DevKey.Equals(String.Empty))
					Messenger.Instance.Messages.Enqueue(new Message(DocBot.Util.Service.PastebinAPI.getPasteURL(paste), MessageType.LogAndChat));
				return;
			}

			//channelstats command
			if (Regex.IsMatch(inputString, @"!streamstats") || Regex.IsMatch(inputString, @"!stats"))
			{
				//get channelname from settings
				String ch = Settings.Instance.IRC_TargetChannel.Replace("#", "");

				//get metadata
				TwitchDataObject st = TwitchAPI.getStreamMetaData(ch);

				//build response string
				String _online = String.Empty;
				String _viewers = String.Empty;
				String _followers = String.Empty;
				String _views = String.Empty;

				//stream online
				if (st._stream.stream != null)
				{
					_online = "online";
					_viewers = st._stream.stream.viewers.ToString();
					_followers = st._stream.stream.channel.followers.ToString();
					_views = st._stream.stream.channel.views.ToString();
				}
				// stream offline
				else
				{
					_online = "offline";
					if (st._channel != null)
					{
						_viewers = "0";
						_followers = st._channel.followers.ToString();
						_views = st._channel.views.ToString();
					}
				}
				Messenger.Instance.Messages.Enqueue(new Message("The Stream is currently " + _online + ", has " + _followers + " follower and " + _views + " views. " + _viewers + " people are watching right now.", MessageType.LogAndChat));

				return;
			}

			//botstatus command
			//if (Regex.IsMatch(inputString, @"!botstatus") || Regex.IsMatch(inputString, @"!status"))
			//{
			//	//build response string
			//	String _message = String.Empty;

			//	//mediaplayer status
			//	//TODO _message += "Mediaplayer status: " + _vlcplayer._vlcplayer.State.ToString();

			//	//modes
			//	_message += ", Autoskip: " + Settings.Instance.Media_AutoSkipThreshold;
			//	//TODO _message += ", Endless: " + Settings.Instance..EndlessStatus.ToString();
			//	//TODO_message += ", Delay Mode: " + _ui.DelayStatus.ToString();

			//	sendMessageToChannel(_message);
			//	return;
			//}

			foreach (CustomCommand c in _customcommands.Items)
				if (c.Command == inputString)
					Messenger.Instance.Messages.Enqueue(new Message(c.Response, MessageType.Chat));
			return;
			#endregion
		}

		public void disconnect()
		{
			// Disconnect IRC client that is connected to given server.
			_ircclient.Quit(clientQuitTimeout, Settings.Instance.IRC_QuitMessage);
			_ircclient.Dispose();

			if (Settings.Instance.DebugMode)
				Messenger.Instance.Messages.Enqueue(new Message("Disconnected.", MessageType.Log));
		}

		/// <summary>
		/// checks if the user has the +o flag in the channel
		/// </summary>
		/// <param name="pSource">the user</param>
		/// <returns>true if yes, false if no</returns>
		private bool checkForOperator(IIrcMessageSource pSource)
		{
			foreach (IrcChannelUser iUser in _ircclient.Channels[0].Users)
			{
				if (pSource.Name.Equals(iUser.User.NickName))
				{
					if (iUser.Modes.Contains('o')) return true;
					return false;
				}
			}
			return false;
		}

		/// <summary>
		/// checks if the user has the +o flag in the channel
		/// </summary>
		/// <param name="pSource">the user</param>
		/// <returns>true if yes, false if no</returns>
		private bool checkForOperator(String pSource)
		{
			foreach (IrcChannelUser iUser in _ircclient.Channels[0].Users)
			{
				if (pSource.Equals(iUser.User.NickName))
				{
					if (iUser.Modes.Contains('o')) return true;
					return false;
				}
			}
			return false;
		}

		#region Connect Command
		void ConnectExecute()
		{
			if (_ircclient != null)
				_ircclient.Dispose();

			_ircclient = new IrcClient();
			if (_ircuserinfo == null)
				return;
			if (_ircclient == null)
				return;

			string server = Settings.Instance.IRC_Serveradress;
			// Create new IRC client and connect to given server.

			_ircclient.FloodPreventer = new IrcStandardFloodPreventer(4, 2000);
			_ircclient.Connected += IrcClient_Connected;
			_ircclient.Disconnected += IrcClient_Disconnected;
			_ircclient.Registered += IrcClient_Registered;
			_ircclient.ConnectFailed += IrcClient_ConnectFailed;
			_ircclient.Disconnected += IrcClient_Disconnected;
			_ircclient.PongReceived += _ircclient_PongReceived;
			_ircclient.PingReceived += _ircclient_PingReceived;
			_ircclient.Error += _ircclient_Error;

			if (Settings.Instance.DebugMode)
				Messenger.Instance.Messages.Enqueue(new Message("connecting...", MessageType.Log));
			// Wait until connection has succeeded or timed out.
			using (var connectedEvent = new ManualResetEventSlim(false))
			{
				_ircclient.Connected += (sender2, e2) => connectedEvent.Set();
				_ircclient.Connect(server, false, _ircuserinfo);
				//if (!connectedEvent.Wait(10000))
				//{
				//	//_ircclient.Dispose();
				//	_log.Add("Connection to " + server + " timed out.");
				//	return;
				//}
			}
		}

		bool CanConnectExecute()
		{
			return true;
		}

		public ICommand Connect { get { return new RelayCommand(ConnectExecute, CanConnectExecute); } }
		#endregion
	}
}
